#include "state_holder.h"
#include "scripthelper.h"

#include "num/crc32.h"
#include "util/mmgr.h"
#include "util/log.h"
#include "vfs/vfs.h"

using namespace LuaPlus;
using namespace script; 

StateHolder::StateHolder() :
	m_pState(0)
{

}

StateHolder::~StateHolder()
{
	Close();
}

void	StateHolder::Load(const std::string& Name)
{
	m_pState = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*m_pState, Name))
	{
		_LOG(MSG_ERROR, "Unable to load Script from " << Name << "!");
		Close();		
	} 
}

void	StateHolder::Close()
{
	if (m_pState)
	{
		LuaState::Destroy( m_pState );
		m_pState = NULL;
	}
}

void	StateHolder::BuildIndex(const std::string& Table, const std::string& Name)
{
	if (!m_pState) return;
	m_IndexName = Table;
	m_KeyName = Name;
	LuaObject	ObjTable = m_pState->GetGlobal(Table.c_str());
	if (!ObjTable.IsTable()) return;
	for (int i=0; i<ObjTable.GetTableCount(); i++)
	{
		int	Index = i+1;
		LuaObject	Obj = ObjTable.GetByIndex(Index);
		if (Obj.IsTable())
		{
			std::string		Key = ScriptHelper::GetTableString(Obj, Name, "");
			if (!Key.empty())
			{
				NodeData*	pData  = new NodeData;
				pData->Index	= Index;
				pData->Name		= Key;
				m_Index.AddElement(Key, pData);
			}
		}
	}
}

int		StateHolder::GetIndex(const std::string& Name)
{
	NodeData*	pData = m_Index.GetElement(Name);
	if (!pData) return -1;
	return pData->Index;
}

bool		StateHolder::IsValid()
{
	if (m_pState==NULL)  return false;
	return true;
}
LuaPlus::LuaObject	StateHolder::GetTable(const std::string& Name)
{
	if (m_pState==NULL) 
	{
		_LOG(MSG_WARNING, "Unable to find Object " << Name << " : Invalid script file");
		return LuaPlus::LuaObject();		
	}
	return m_pState->GetGlobal(Name.c_str());
}


LuaPlus::LuaObject	StateHolder::GetNode(const std::string& Name)
{
	if (m_pState==NULL) 
	{
		_LOG(MSG_WARNING, "Unable to find Object " << Name << " : Invalid script file");
		return LuaPlus::LuaObject();		
	}
	int	Index	= GetIndex(Name);
	if (Index < 0) 
	{
		_LOG(MSG_WARNING, "Unable to find Object " << Name << " :  cannot find object ");
		return LuaPlus::LuaObject();		
	}
	LuaPlus::LuaObject	Table = m_pState->GetGlobal(m_IndexName.c_str());
	if (!Table.IsTable())
	{
		_LOG(MSG_WARNING, "Unable to find Object " << Name << " :  Invalid Script Table : " << m_IndexName);
		return LuaPlus::LuaObject();		
	}
	LuaPlus::LuaObject		Obj = Table.GetByIndex(Index);
	if (!Obj.IsTable())
	{
		_LOG(MSG_WARNING, "Unable to find Object " << Name << " :  Invalid table entry");
		return LuaPlus::LuaObject();		
	}
/*	// sanity check?
	std::string	ObjName = ScriptHelper::GetTableString(Obj,m _KeyName);
	if (strcmpi(Name.c_str(), ObjName.c_str()) != 0)
	{
		_LOG(MSG_WARNING, "Unable to load building: name mismatch!" << Name);
		return NULL;		
	}*/

	return Obj;
}


std::string			StateHolder::GetString(const std::string& Table, const std::string& Name, const std::string& Default)
{
	LuaPlus::LuaObject	Obj = GetTable(Table);
	if (Obj.GetState()) return ScriptHelper::GetTableString(Obj, Name, Default);
	return Default;
}
float				StateHolder::GetFloat(const std::string& Table, const std::string& Name, float Default)
{
	LuaPlus::LuaObject	Obj = GetTable(Table);
	if (Obj.GetState()) return ScriptHelper::GetTableFloat(Obj, Name, Default);
	return Default;
}

int					StateHolder::GetInt(const std::string& Table, const std::string& Name, int Default)
{
	LuaPlus::LuaObject	Obj = GetTable(Table);
	if (Obj.GetState()) return ScriptHelper::GetTableInt(Obj, Name, Default);
	return Default;
}

bool				StateHolder::GetBool(const std::string& Table, const std::string& Name, bool Default)
{
	LuaPlus::LuaObject	Obj = GetTable(Table);
	if (Obj.GetState()) return ScriptHelper::GetTableBool(Obj, Name, Default);
	return Default;
}